<?php
global $CFG;
require_once($CFG->dirroot . '/blocks/formal_langs/langs_src/tools/JLexPHP/jlex.php');
require_once($CFG->dirroot . '/blocks/formal_langs/tokens_base.php');
require_once($CFG->dirroot . '/blocks/formal_langs/langs_code/system/lex_pattern_parser.php');
%%

%class lex_pattern_lexer
%function next_token
%char
%line
%state REGEXP
%unicode

ALPHA         = [A-Za-z_]
DIGIT         = [0-9]
ALPHA_NUMERIC = {ALPHA}|{DIGIT}
ID            = {ALPHA}({ALPHA_NUMERIC})*
WHITE_SPACE   = [\ \n\r\t\f]
COPY          = copy
CREATE        = create
APPEND        = append
ERROR         = error
    
%{
    private $token_count = 0;

    public $errors = array();

    // buffer for accumulating regexp
    private $regexp_buffer;
    // begin and end line for position
    private $regexp_pos_bl, $regexp_pos_el;
    // begin and end colon for position
    private $regexp_pos_bc, $regexp_pos_ec;

    private function return_token($type, $desc) {
        // create token object
        $res = new block_formal_langs_token_base(NULL, $type, $this->yytext(), $this->return_pos(), $this->token_count);
        $res->set_description($desc);
        // increase token count
        $this->token_count++;

        return $res;
    }

    private function return_pos() {
        $begin_line = $this->yyline;
        $begin_col = $this->yycol;

        $lines = explode("\n", $this->yytext());
        $num_lines = count($lines);

        $end_line = $begin_line + $num_lines - 1;
        $end_col = strlen($lines[$num_lines -1]);

        $res = new block_formal_langs_node_position($begin_line, $end_line, $begin_col, $end_col);
        
        return $res;
    }

    private function return_regexp() {
        // create position object
        $pos = new block_formal_langs_node_position($this->regexp_pos_bl, $this->regexp_pos_el, $this->regexp_pos_bc, $this->regexp_pos_ec);
        // create token object
        $res = new block_formal_langs_token_base(NULL, lex_pattern_yyParser::REGEXP, $this->regexp_buffer, $pos, $this->token_count);
        $res->set_description("REGEXP");
        $this->token_count++;
        $this->regexp_buffer = '';

        return $res;
    }
%}

%%

<YYINITIAL> {COPY}   { return $this->return_token(lex_pattern_yyParser::COPY, "COPY"); }
<YYINITIAL> {CREATE} { return $this->return_token(lex_pattern_yyParser::CREATE, "CREATE"); }
<YYINITIAL> {APPEND} { return $this->return_token(lex_pattern_yyParser::APPEND, "APPEND"); }
<YYINITIAL> {ERROR}  { return $this->return_token(lex_pattern_yyParser::ERROR, "ERROR"); }

<YYINITIAL> \" {
    $this->yybegin(self::REGEXP);
    $this->regexp_buffer = '';
    $this->regexp_pos_bl = $this->yyline;
    $this->regexp_pos_bc = $this->yycol;
 }

<REGEXP> \\\" { $this->regexp_buffer .= "\""; }

<REGEXP> \" {
    $this->regexp_pos_el = $this->yyline;
    $this->regexp_pos_ec = $this->yycol + 1;
    $this->yybegin(self::YYINITIAL);    
    return $this->return_regexp();
 }

<REGEXP> [^\\\"]* { $this->regexp_buffer .= $this->yytext(); }
<REGEXP> \\[^\"] { $this->regexp_buffer .= $this->yytext(); }

<YYINITIAL> \)   { return $this->return_token(lex_pattern_yyParser::RPAREN, "RPAREN"); }
<YYINITIAL> \(   { return $this->return_token(lex_pattern_yyParser::LPAREN, "LPAREN"); }
<YYINITIAL> :    { return $this->return_token(lex_pattern_yyParser::COLON, "COLON"); }
<YYINITIAL> ;    { return $this->return_token(lex_pattern_yyParser::SEMICOLON, "SEMICOLON"); }
<YYINITIAL> =    { return $this->return_token(lex_pattern_yyParser::EQUAL, "EQUAL"); }
<YYINITIAL> ->   { return $this->return_token(lex_pattern_yyParser::ARROW, "ARROW"); }
<YYINITIAL> {ID} { return $this->return_token(lex_pattern_yyParser::ID, "ID"); }

<YYINITIAL> {WHITE_SPACE}+ {}

. { /* process bad input */
    $error = array();
    $error['line'] = $this->yyline;
    $error['column'] = $this->yycol;
    $error['input'] = $this->yytext();

    $this->errors[] = $error;
}
